package com.bjb.vr.common.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjb.vr.common.ao.UpgradeAo;
import com.bjb.vr.common.constant.AliOssConstants;
import com.bjb.vr.common.constant.ThreadLocalConstant;
import com.bjb.vr.common.constant.UpgradeConstants;
import com.bjb.vr.common.dto.SysTenant;
import com.bjb.vr.common.dto.SysUpgrade;
import com.bjb.vr.common.mapper.SysTenantMapper;
import com.bjb.vr.common.mapper.SysUpgradeMapper;
import com.bjb.vr.common.result.BaseResult;
import com.bjb.vr.common.result.CommonResult;
import com.bjb.vr.common.utils.AliyunOssUtil;
import com.bjb.vr.common.utils.ThreadLocalUtil;
import com.bjb.vr.common.utils.XrVersionUtil;
import com.bjb.vr.common.vo.SysTenantVo;
import com.bjb.vr.common.vo.UmsAccountVo;
import com.bjb.vr.common.vo.UpgradeVo;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author admin
 * @description 针对表【sys_upgrade】的数据库操作Service实现
 * @createDate 2022-07-22 17:02:07
 */
@Slf4j
@Service
public class SysUpgradeService extends ServiceImpl<SysUpgradeMapper, SysUpgrade> {

    private static AliyunOssUtil ossUtil = null;

    static {
        ossUtil = new AliyunOssUtil.Builder().build(AliOssConstants.ENDPOINT, AliOssConstants.ACCESS_KEY_ID, AliOssConstants.ACCESS_KEY_SECRET);
    }

    @Resource
    private SysUpgradeMapper upgradeMapper;

    @Resource
    private SysTenantMapper tenantMapper;

    @Resource
    private SysTenantService tenantService;

    /**
     * 升级包列表查询
     *
     * @param upgradeAo
     * @return
     */
    public IPage<UpgradeVo> queryUpgradeList(UpgradeAo upgradeAo) {
        MPJLambdaWrapper<UpgradeVo> mpjLambdaWrapper = new MPJLambdaWrapper<>();
        mpjLambdaWrapper.select(SysUpgrade::getId)
                .select(SysUpgrade::getType)
                .select(SysUpgrade::getTenantId)
                .select(SysUpgrade::getPackageName)
                .select(SysUpgrade::getVersion)
                .select(SysUpgrade::getPackageSize)
                .select(SysUpgrade::getPublishStatus)
                .select(SysUpgrade::getPackageType)
                .select(SysUpgrade::getCreator)
                .select(SysUpgrade::getGmtCreate);
        mpjLambdaWrapper.eq(Objects.nonNull(upgradeAo.getPublishStatus()), SysUpgrade::getPublishStatus, upgradeAo.getPublishStatus());
        mpjLambdaWrapper.eq(StringUtils.isNotBlank(upgradeAo.getPackageType()), SysUpgrade::getPackageType, upgradeAo.getPackageType());
        mpjLambdaWrapper.like(StringUtils.isNotBlank(upgradeAo.getPackageName()), SysUpgrade::getPackageName, upgradeAo.getPackageName());
        mpjLambdaWrapper.orderByDesc(SysUpgrade::getId);
        IPage<UpgradeVo> voIPage = upgradeMapper.selectJoinPage(new Page<>(upgradeAo.getCurrent(), upgradeAo.getSize()), UpgradeVo.class, mpjLambdaWrapper);
        buildVos(voIPage.getRecords());
        return voIPage;
    }

    /**
     * 封装vo对象
     *
     * @param records
     * @return
     */
    private void buildVos(List<UpgradeVo> records) {
        for (UpgradeVo record : records) {
            String tenantId = record.getTenantId();
            SysTenant sysTenant = tenantService.selectOneSysTenantByTenantId(tenantId);
            if (Objects.nonNull(sysTenant)) {
                record.setTenantName(sysTenant.getTenantName());
            }
        }
    }

    /**
     * 发布升级包
     *
     * @param upgradeAo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean insert(UpgradeAo upgradeAo) {
        String[] tenantIds = upgradeAo.getTenantIds();
        String timeStamp = String.valueOf(System.currentTimeMillis());
        try {
            // 插入升级表
            for (String tenantId : tenantIds) {
                UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
                umsAccountVo.setTempTenantId(tenantId);
                SysUpgrade upgrade = new SysUpgrade();
                BeanUtils.copyProperties(upgradeAo, upgrade);
                upgrade.setServerUrl(upgradeAo.getPackageUrl());
                upgrade.setTenantId(tenantId);
                upgrade.setTimestamp(timeStamp);
                upgradeMapper.insert(upgrade);
            }
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 升级客户列表查询
     *
     * @param upgradeAo
     * @return
     */
    public IPage<SysTenantVo> queryTenantList(UpgradeAo upgradeAo) {
        MPJLambdaWrapper<SysTenant> joinQueryWrapper = new MPJLambdaWrapper<>();
        joinQueryWrapper.select(SysTenant::getTenantId)
                .select(SysTenant::getTenantName);
        IPage<SysTenantVo> pages = tenantMapper.selectJoinPage(new Page<>(upgradeAo.getCurrent(), upgradeAo.getSize()), SysTenantVo.class, joinQueryWrapper);
        return pages;
    }

    /**
     * 编辑升级包
     *
     * @param upgradeAo
     * @return
     */
    public boolean updateInfo(UpgradeAo upgradeAo) {
        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        umsAccountVo.setTempTenantId(upgradeAo.getTenantId());
        SysUpgrade upgrade = new SysUpgrade();
        BeanUtils.copyProperties(upgradeAo, upgrade);
        upgrade.setServerUrl(upgradeAo.getPackageUrl());
        try {
            this.updateById(upgrade);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 查询单个升级包数据
     *
     * @param upgradeAo
     * @return
     */
    public UpgradeVo queryOne(UpgradeAo upgradeAo) {
        UpgradeVo upgradeVo = upgradeMapper.selectByIdNo(upgradeAo.getId());
        return upgradeVo;
    }

    /**
     * 删除单个升级包数据
     *
     * @param upgradeAo
     * @return
     */
    public boolean delete(UpgradeAo upgradeAo) {
        try {
            upgradeMapper.deleteById(upgradeAo.getId());
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 触发升级
     *
     * @param upgradeAo
     * @return
     */
    public boolean release(UpgradeAo upgradeAo) {
        SysUpgrade upgrade = new SysUpgrade();
        BeanUtils.copyProperties(upgradeAo, upgrade);
        try {
            upgradeMapper.updateById(upgrade);
            return true;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 获取前置机、一体机最新版本更新信息
     *
     * @return
     */
    public JSONArray queryLatestVersion() {
        UmsAccountVo umsAccountVo = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
        // 封装返回结果
        JSONArray jsonArray = new JSONArray();
        UpgradeVo upgradeVo = upgradeMapper.selectOneByTenantId(umsAccountVo.getTenantId(), UpgradeConstants.ZIP);
        if (Objects.nonNull(upgradeVo)) {
            upgradeVo.setWebUrl(ossUtil.getFileUrl(upgradeVo.getWebUrl()));
            upgradeVo.setServerUrl(ossUtil.getFileUrl(upgradeVo.getServerUrl()));
            JSONObject object = (JSONObject) JSONObject.toJSON(upgradeVo);
            jsonArray.add(object);
        }
        return jsonArray;
    }


    public UpgradeVo queryDevLatestVersion(String tenantId) {

        List<UpgradeVo> upgradeVoList = upgradeMapper.queryDevLatestVersion(tenantId);
        if (upgradeVoList == null || upgradeVoList.isEmpty()) {
            return null;
        }
        //版本最大的记录已升级返回null
        UpgradeVo upgradeVo = upgradeVoList.get(0);
        if (upgradeVo.getComplete() == 1) {
            return null;
        }
        //最大版本为强制未升级的直接返回
        if (upgradeVo.getForceUpgrade() == 1) {
            return upgradeVo;
        }
        //最大版本为非强制未升级的，查找最大版本为强制的记录。
        List<UpgradeVo> forceUpDevLatestVersionList = upgradeMapper.queryForceUpDevLatestVersion(tenantId);
        if (forceUpDevLatestVersionList == null || forceUpDevLatestVersionList.isEmpty()) {
            return upgradeVo;
        }
        UpgradeVo forceUpgradeVo = forceUpDevLatestVersionList.get(0);
        //强制已升级，返回非强制未升级的记录
        if (forceUpgradeVo.getComplete() == 1) {
            return upgradeVo;
        } else {//强制未升级，返回强制未升级的
            return forceUpgradeVo;
        }
    }


    /**
     * 校验发布数据版本规则
     *
     * @param upgradeAo
     * @return
     */
    public BaseResult checkVersion(UpgradeAo upgradeAo) {
        // 校验版本号规则是否正确
        boolean valid = XrVersionUtil.isValidVersion(upgradeAo.getVersion());
        if (!valid) {
            return CommonResult.Fail(upgradeAo.getPackageType() + "包版本规则校验失败！");
        }
        // 校验为发布版本号是否已存在
        List<String> tenantNames = new ArrayList<>();
        for (String tenantId : upgradeAo.getTenantIds()) {
            Integer exist = upgradeMapper.existVersion(upgradeAo.getVersion(), upgradeAo.getPackageType(), tenantId);
            if (exist != null) {
                SysTenant sysTenant = tenantService.selectOneSysTenantByTenantId(tenantId);
                tenantNames.add(sysTenant.getTenantName());
            }
        }
        if (tenantNames.size() > 0) {
            return CommonResult.Fail("租户【" + tenantNames + "】" + upgradeAo.getPackageType() + "包当前版本已存在!");
        }

        // 校验为发布版本号是否大于已发布版本号
        StringBuilder builder = new StringBuilder();
        for (String tenantId : upgradeAo.getTenantIds()) {
            String latestVersion = upgradeMapper.queryLatestVersion(upgradeAo.getPackageType(), tenantId);
            if (StringUtils.isNotBlank(latestVersion)) {
                // 比较版本号大小
                boolean greater = XrVersionUtil.isGreaterVersion(latestVersion, upgradeAo.getVersion());
                if (!greater) {
                    SysTenant sysTenant = tenantService.selectOneSysTenantByTenantId(tenantId);
                    builder.append("租户【").append(sysTenant.getTenantName()).append("】").append(upgradeAo.getPackageType()).append("包版本应大于").append(latestVersion).append(";");
                }
            }
        }
        if (builder.length() > 0) {
            return CommonResult.Fail(builder.toString());
        }
        return CommonResult.Ok();
    }
}




